/*
 * Copyright (C) 2020 Agrui
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "TransactionList.h"
#include "OSMemory.h"
#include "ParameterCheck.h"

TransactionList* newTransactionList() {
    TransactionList* list = OS_ALLOC_AND_RESET(TransactionList);
    PARAMTER_CHECK_RETURN_NULL(list);
    list->lock = newLock();
    if (!list->lock) {
        OS_FREE(list);
        return NULL;
    }
}

TransactionNode* createTransactionNode(int id, void* userData) {
    TransactionNode* newNode = OS_ALLOC_AND_RESET(TransactionNode);
    if (!newNode) {
        return NULL;
    }

    newNode->id = id;
    newNode->userData = userData;
    newNode->next = NULL;

    return newNode;
}

void appendTransactionNode(TransactionList* list, int id, void* userData) {
    if (!list) {
        return;
    }

    TransactionNode* newNode = createTransactionNode(id, userData);
    if (!newNode) {
        return;
    }

    lock(list->lock);

    if (!list->header) {
        list->header = newNode;
    } else {
        TransactionNode* temp = list->header;
        while (temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = newNode;
    }

    unlock(list->lock);
}

TransactionNode* getTransactionNode(TransactionList* list, int id) {
    TransactionNode* node = NULL;
    if (!list) {
        return NULL;
    }

    lock(list->lock);

    TransactionNode* temp = list->header;
    TransactionNode* prev = NULL;

    while (temp != NULL && temp->id != id) {
        prev = temp;
        temp = temp->next;
    }

    if (temp == NULL) {
        unlock(list->lock);
        return NULL;
    }

    node = temp;

    if (prev == NULL) {
        list->header = temp->next;
    } else {
        prev->next = temp->next;
    }

    unlock(list->lock);
    return node;
}

void deleteTransactionNode(TransactionList* list, int id) {
    if (!list) {
        return;
    }

    lock(list->lock);
    TransactionNode* temp = list->header;
    TransactionNode* prev = NULL;

    if (temp != NULL && temp->id == id) {
        list->header = temp->next;
        OS_FREE(temp);
        unlock(list->lock);
        return;
    }

    while (temp != NULL && temp->id != id) {
        prev = temp;
        temp = temp->next;
    }

    if (temp == NULL) {
        unlock(list->lock);
        return;
    }

    prev->next = temp->next;
    OS_FREE(temp);

    unlock(list->lock);
}


void deleteTransactionList(TransactionList* list) {
    if (list && list->lock) {
        lock(list->lock);
        TransactionNode* temp = list->header;
        TransactionNode* nextNode;

        while (temp != NULL) {
            nextNode = temp->next;
            OS_FREE(temp);
            temp = nextNode;
        }
        list->header = NULL;
        unlock(list->lock);
        deleteLock(list->lock);
        OS_FREE(list);
    }
}

